pub fn run_examples() {
  println!("===== Rust 所有权示例 =====\n");

  // 1. 所有权基本规则
  println!("1. 所有权基本规则:");
  println!("   - 每个值在 Rust 中都有一个被称为其所有者的变量");
  println!("   - 值在任一时刻只能有一个所有者");
  println!("   - 当所有者离开作用域，值将被丢弃");
  example_1();

  // 2. 所有权移动（Move）
  println!("\n2. 所有权移动（Move）:");
  example_2();

  // 3. 克隆（Clone）
  println!("\n3. 克隆（Clone）数据:");
  example_3();

  // 4. 复制（Copy）特性
  println!("\n4. 复制（Copy）特性. 实现了 Copy 特性的类型赋值时不会转移所有权，而是复制:");
  example_4();

  // 5. 可变性
  println!("\n5. 可变性. 当所有权转移时，可变性也可以随之改变:");
  example_5();

  // 6. 部分 move
  println!("\n6. 部分 move. 当解构一个变量时，可以同时使用 move 和引用模式绑定的方式。部分 move 就会发生:");
  example_6();
}

// 1. 所有权基本规则
fn example_1() {
  // 创建一个字符串
  let s1 = String::from("你好");
  println!("   外部作用域::创建字符串 s1: {}", s1);

  // 变量作用域
  {
    let s2 = String::from("作用域内的字符串");
    println!("   内部作用域::s2: {}", s2);
    // s2 在这里离开作用域并被丢弃
  }
  // 此处不能使用 s2，它已经被丢弃
  println!("   外部作用域中::s2 已离开内部作用域并被丢弃");
}

// 2. 所有权移动（Move）
fn example_2() {
  // 对于堆上的数据，赋值会导致所有权转移
  let s1 = String::from("hello");
  println!("   let s1 = String::from(\"hello\");");

  let s2 = s1; // s1 的所有权移动到 s2
  println!("   let s2 = s1");

  // 此时 s1 不再有效，取消下面的注释会导致编译错误
  // borrow of moved value: `s1`
  // value borrowed here after move
  // println!("   尝试使用 s1: {}", s1);
  println!("   // s1 已失效，若使用 s1, 会报错 borrow of moved value: `s1`. value borrowed here after move");

  println!("   takes_ownership(s2)");
  // 对于函数也是如此
  takes_ownership(s2);
  
  // s2 不再有效
  // println!("   尝试使用 s2: {}", s2); // 编译错误
  println!("   // 到此因 s2 的所有权已转移到函数中，无法再使用");
}

// 函数获取所有权
fn takes_ownership(s: String) {
  println!("   函数 takes_ownership 获取了字符串的所有权: {}. 并结束调用", s);
  // s 在这里离开作用域并被丢弃
}


// 3. 克隆数据
fn example_3() {
  let s1 = String::from("Hello");
  println!("   let s1 = String::from(\"hello\");");

  let s2 = s1.clone(); // 深拷贝，不会转移所有权
  println!("   let s2 = s1.clone()");
  println!("   s1: {}, s2: {}", s1, s2);
  // s1 仍然有效，因为我们克隆了数据而不是移动
}


// 4. 复制特性
fn example_4() {
  // 实现了 Copy 特性的类型赋值时不会转移所有权，而是复制
  let x = (1, 2, (), "hello");
  println!("   let x = (1, 2, (), \"hello\");");
  let y = x;
  println!("   let y = x // 复制 x 到 y, x 仍旧有效");
  println!("   x:{:?}, y:{:?}", x, y);

  // 实现了 Copy 特性的类型:
  println!("   实现了 Copy 特性的类型:");
  println!("   - 所有整数类型，如 i32, u64");
  println!("   - 布尔类型 bool");
  println!("   - 字符类型 char, 字符串切片 &str");
  println!("   - 浮点类型，如 f64");
  println!("   - 元组，当且仅当其包含的所有类型都实现了 Copy 时");
  println!("   - 数组，当且仅当其元素类型实现了 Copy 时");
}

// 5. 可变性
fn example_5() {
  let s = String::from("hello");
  let mut s1 = s;
  s1.push_str("world");
  println!("   let s = String::from(\"hello\");");
  println!("   let mut s1 = s; // 转移了 s 给 s1, 并且 s1 成为可变引用");
  println!("   s1.push_str(\"world\");");
}

// 6. 部分 move
fn example_6() {
  let x = (1, false, String::from("world"));
  let (s1, s2, s3) = x;
  println!("   let x = (1, false, String::from(\"world\"));");
  println!("   let (s1: i32, s2: bool, s3: String) = x;");
  println!("   s1:{}, s2:{}, s3:{}", s1, s2, s3);
  println!("   x // 报错 borrow of partially moved value: `x`, 这就是部分借用");
  println!("   // 补充说明: 若 x 中无 String 类型, 而是 &str 类型, 那么 x 解构后还是可用的");
}